05 - Workers/01 - Serializable Elements.js (34 lines of code) (raw):
// It could be possible to run React Components in a separate worker that then
// communicates with a React component in another worker.
import SameThreadComponent from "Foo"; // React class
const CrossThreadComponent = "Bar"; // Just a string module ID
const AnotherCrossThreadComponent = "Baz"; // Another string module ID
// The props of a cross-thread element must be serializable across the worker
// boundary. Functions are treated as asynchronous callbacks with serializable
// arguments.
class App {
render() {
return (
<SameThreadComponent prop="foo">
<CrossThreadComponent prop="bar" callback={data => log(data)}>
<AnotherCrossThreadComponent some={{ prop: 'baz' }} />
</CrossThreadComponent>
</SameThreadComponent>
);
}
}
// The ReactComponent is instantiated on the other side of the worker and
// rendered top-down using the normal React reconciliation. State may live on
// the other side of the worker boundary.
// Normally, it is illegal to nest same-thread components inside a cross-thread
// component:
class CounterExample {
render() {
return (
<CrossThreadComponent prop="bar" callback={data => log(data)}>
{/* Illegal */}<SameThreadComponent prop="foo" />{/* Don't do this */}
</CrossThreadComponent>
);
}
}
// This doesn't work because a React parent component is responsible for
// resolving its children. The CrossThreadComponent would have to block
// rendering to come back to this thread to ask the SameThreadComponent to
// resolve itself. This defeats the purpose of asynchronously resolving these.
// However, luckily we have a solution around that using prerendering which
// we'll cover in the next chapter.